package com.zx.baofu.alcohol.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zx.baofu.alcohol.mapper.*;
import com.zx.baofu.alcohol.model.*;
import com.zx.baofu.alcohol.service.PeriodsAddressService;
import com.zx.baofu.alcohol.service.PeriodsService;
import com.zx.baofu.alcohol.service.PrizeService;
import com.zx.baofu.alcohol.service.UserService;
import com.zx.baofu.alcohol.util.MapUtil;
import com.zx.baofu.alcohol.util.MyStringUtil;
import com.zx.baofu.alcohol.util.PageUtil;
import com.zx.baofu.alcohol.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.ZoneId;
import java.util.*;

@Component
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private SettingMapper settingMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private PrizeService prizeService;
    @Autowired
    private PeriodsMapper periodsMapper;
    @Autowired
    private PeriodsAddressMapper periodsAddressMapper;
    /**
     *
     * @param unionid
     * @param nickName
     * @param img
     * @param longitude
     * @param latitude
     * @return {"code":200,"msg":"添加用户成功"}
     *  {"code":500,"msg":"用户已存在"}
     */
    @Override
    public Result addUser(String unionid, String nickName, String img, Double longitude, Double latitude) {
        //活动时间的限制
        int available = settingMapper.availableTime();
        if (available <= 0){
            return new Result().fail("当前时间不在活动时间范围内");
        }
        if (MyStringUtil.isNullorEmpty(unionid)){
            return new Result().fail("未获取到用户标识，请返回重试");
        }
        //用户区域的限制
        if(null == longitude || null == latitude){
            return new Result().fail("未能获取您的位置，请退出重新登陆");
        }
        //保定中心点的GPS坐标
        List<Periods> periodsList= periodsMapper.getAllPeriods();
        double baodingLongitude = 115.4883922186;
        double baodingLatitude = 38.8712720633;
        Integer district=null;
        //判断用户在不在四期活动的时间内
        for (int i = 0; i < periodsList.size(); i++) {
            Date beginTime=  Date.from(periodsList.get(i).getStartDate().atZone(ZoneId.systemDefault()).toInstant());
            Date endTime=  Date.from(periodsList.get(i).getEndDate().atZone(ZoneId.systemDefault()).toInstant());
            boolean res=belongCalendar(new Date(),beginTime,endTime);
            if(res){
                PeriodsAddress periodsAddress=periodsAddressMapper.getByPeriodsId(periodsList.get(i).getId());
                baodingLongitude=Double.parseDouble(periodsAddress.getLongitude());
                baodingLatitude=Double.parseDouble(periodsAddress.getLatitude());
                district=periodsAddress.getDistrict();
            }
            System.out.println(periodsList.get(i));
        }
        //未查到时间活动结束
        if(district==null){
            return  new Result().fail("活动已结束");
        }
        System.out.println(district);
        double meters = MapUtil.distance(baodingLongitude, baodingLatitude, longitude, latitude);
        if (meters > district * 1000){
            //大于meters即为不在活动范围
            return  new Result().fail("您当前不在活动范围内");
        }

//        JSONObject res = MapUtil.GPSToBaiDu(longitude, latitude);
//        if (res.getIntValue("status") != 0){
//            return new Result().fail("未能识别您所在的位置，请退出重新登陆");
//        }
//        double baiduLongitude = JSONObject.parseObject(res.getJSONArray("result").get(0).toString()).getDouble("x");
//        double baiduLatitude = JSONObject.parseObject(res.getJSONArray("result").get(0).toString()).getDouble("y");
//        JSONObject addressRes = MapUtil.getCityFromLngAndlat(baiduLongitude, baiduLatitude);
//        if (addressRes.getIntValue("status") != 0){
//            return new Result().fail("转换位置失败，请退出重新登陆");
//        }
//        String city = addressRes.getJSONObject("result").getJSONObject("addressComponent").getString("city");
//        if (!"保定市".equals(city)){
//            return  new Result().fail("本次活动仅支持保定地区用户参加，您当前不在活动范围内");
//        }

        //校验用户是否已存在
        int checkRes = userMapper.checkUserUnionId(unionid);
        if (checkRes > 0){
            return new Result().success("用户已存在");
        }
        User user = new User();
        user.setUnionid(unionid);
        user.setNickname(nickName);
        user.setImg(img);
        int addRes = userMapper.addUser(user);
        if (addRes <= 0){
            return new Result().fail("保存数据失败");
        }
        return new Result().success("添加用户成功");
    }

    @Override
    public Result helpUser(String helpUnionId, String helpedUnionId) {
        if (MyStringUtil.isNullorEmpty(helpedUnionId, helpUnionId)){
            return new Result().fail("未获取到用户标识，请返回重试");
        }
        Integer res=userMapper.checkUserUnionId(helpUnionId);
        if(res==0){
            return new Result().fail("不在活动时间或活动范围内");
        }
        //活动时间的限制
        int available = settingMapper.availableTime();
        if (available <= 0){
            return new Result().fail("当前时间不在活动时间范围内");
        }
        if (helpedUnionId.equals(helpUnionId)){
            return new Result().fail("不能给自己倒酒");
        }
        //不能重复帮助
        int checkRes = userMapper.checkHelp(helpUnionId, helpedUnionId);
        if(checkRes > 0){
            return new Result().fail("您已帮好友倒过酒，不能重复倒酒");
        }
        //被帮助用户修改酒量
        int alcoholNum = 0;
        //被帮助的次数
        int helpedTimes = userMapper.countHelpedTimes(helpedUnionId);
        //当前酒量
        int currentAlcoholNum = userMapper.userAlcoholNum(helpedUnionId);
        System.out.println("当前酒量"+currentAlcoholNum);
        if (currentAlcoholNum < 36){
            alcoholNum = 1;
        }else if(currentAlcoholNum>=36){
            //alcoholNum = caclAlcoholNum(currentAlcoholNum, helpedTimes);
            if (alcoholNum == 0){
                return new Result().fail("好友已达成抽奖条件，不继续增加酒量");
            }
        }
        int updateRes = userMapper.updateUserAlcoholNum(helpedUnionId, alcoholNum);
        if (updateRes <= 0){
            return new Result().fail("您的好友已达成抽奖条件，不能继续增加酒量");
        }
        //添加倒酒记录
        UserHelp userHelp = new UserHelp();
        userHelp.setAlcoholNum(alcoholNum);
        userHelp.setHelpUnionid(helpUnionId);
        userHelp.setHelpedUnionid(helpedUnionId);
        int addRes = userMapper.addUserHelp(userHelp);
        if (addRes <= 0){
            return new Result().fail("保存数据失败");
        }

        //再次获取当前酒量
        currentAlcoholNum = userMapper.userAlcoholNum(helpedUnionId);
        System.out.println("再次获取为"+currentAlcoholNum);
        //判断用户是否达成抽奖条件
        if (currentAlcoholNum >= 36){
            //修改状态
            userMapper.updateUserLottery(helpedUnionId, EnumLottery.WAITLOTTERY.getId());
        }
        return new Result().success("帮助好友倒酒成功", alcoholNum);
    }

    @Override
    public Result userLottery(String unionid) {
        //添加抽奖纪录
        UserLottery userLottery = new UserLottery();
        userLottery.setUserUnionid(unionid);
        //活动时间的限制
        int available = settingMapper.availableTime();
        if (available <= 0){
            return new Result().fail("当前时间不在活动时间范围内");
        }
        // 待抽奖状态改到前面先校验用户能否抽奖
        int status = userMapper.userLotteryStatus(unionid);
        if (EnumLottery.WAITLOTTERY.getId() != status){
            if (EnumLottery.UNABLELOTTERY.getId() == status){
                return new Result().fail("您还不能抽奖，请继续邀请好友倒酒");
            }
            if (EnumLottery.ALREADYLOTTERY.getId() == status){
                return new Result().fail("您已经抽过奖，不能重复抽奖");
            }
            return new Result().fail("您当前不能抽奖");
        }
        //奖品上限的限制
        int todayNum = orderMapper.todayPrizeNum();
        System.out.println(todayNum);
        DailyLimit dl = settingMapper.getDailyLimit();
        System.out.println("----------"+dl.getLimit());
        if (todayNum >= dl.getLimit()){
            //抽奖纪录赋值
            userLottery.setWin(0);
            userLottery.setPrizeName("");
            userMapper.addUserLottery(userLottery);
            return new Result().unPrize("很遗憾您未中奖");
        }

        //校验酒量 两种方式
        System.out.println("当前用户"+unionid);
        int currentAlcoholNum = userMapper.userAlcoholNum(unionid);
        System.out.println(userMapper.userAlcoholNum(unionid));
        //int totalAlcoholNum = userMapper.userTotalAlcoholNum(unionid);
        if(currentAlcoholNum < 36 ){
            return new Result().fail("您积累的酒量还不够100%，请继续邀请好友倒酒");
        }

        // 订单状态
        int orderCheck = userMapper.countUserOrder(unionid);
        if (orderCheck > 0){
            return new Result().fail("您已有中奖订单，请不要重复抽奖");
        }
        //执行抽奖
        //获取设置的中奖概率
        //int probability = userMapper.lotteryProbability();
        List<LotteryProbability> lotteryProbabilities=orderMapper.getAllLottery();
        //虚拟长度为100的数组，填充数据，乱序
        List<Integer> list = probabilityArray();
        //if (list.get(0) <= probability) {
        String msg="";
            //抽奖纪录赋值
        if(list.get(0)<=lotteryProbabilities.get(0).getProbability()){
            //一等奖
            userLottery.setWin(1);
            msg="一等奖";
        }else if(list.get(0)<=(lotteryProbabilities.get(1).getProbability()+lotteryProbabilities.get(0).getProbability())){
            //二等奖
            userLottery.setWin(2);
            msg="二等奖";
        }else if(list.get(0)<=100-(lotteryProbabilities.get(1).getProbability()+lotteryProbabilities.get(0).getProbability())){
            //三等奖
            userLottery.setWin(3);
            msg="三等奖";
        }
            //中奖生成订单
            UserOrder order = new UserOrder();
            order.setUserUnionid(unionid);
            createOrderNum(order);
            createPrizeInfo(order,userLottery.getWin());
            // createShopInfo(order);
            userMapper.addUserOrder(order);
            userLottery.setPrizeName(order.getPrizeName());
            userLottery.setPrizeNum(1);
            userLottery.setPrizeValue(order.getPrizeValue());
            userMapper.addUserLottery(userLottery);
            //设置已抽奖
            userMapper.updateUserLottery(unionid, EnumLottery.ALREADYLOTTERY.getId());
            return new Result().success("恭喜您中奖"+msg, order);
        //}
        /*抽奖纪录赋值
        userLottery.setWin(0);
        userLottery.setPrizeName("");
        userMapper.addUserLottery(userLottery);*/
        //设置已抽奖
        //userMapper.updateUserLottery(unionid, EnumLottery.ALREADYLOTTERY.getId());
        //return new Result().unPrize("很遗憾您未中奖");
    }

    @Override
    public Result backUserList(Integer pageNum, Integer pageSize) {
        int start = PageUtil.caclStart(pageNum, pageSize);
        List<User> list = userMapper.backUserList(start, pageSize);
        if (list.size() <= 0){
            return new Result().fail("没有符合条件的数据");
        }
        int totalNum = userMapper.countBackUserList();
        int totalPage = PageUtil.caclTotalPage(pageSize, totalNum);
        return new Result().success("查询成功", list, totalNum, totalPage);
    }

    @Override
    public Result manageLogin(String account, String password) {
        if(MyStringUtil.isNullorEmpty(account, password)){
            return new Result().fail("账号密码不能为空，请填写完整");
        }
        Manager manager = userMapper.manageLogin(account);
        if (null == manager){
            return new Result().fail("该管理员不存在，请检查账号");
        }
        if ( ! password.equals(manager.getPassword())){
            return new Result().fail("密码错误，请检查密码");
        }
        return new Result().success("登陆成功", manager);
    }

    @Override
    public Result getUserInfo(String unionid){
        User user = userMapper.getUserInfo(unionid);
        if (null == user){
            return new Result().fail("用户不存在");
        }
        return new Result().success("查询完成", user);
    }

    @Override
    public Result getWinList() {
        List<UserLottery> list = orderMapper.winList();
        return new Result().success("查询成功", list);
    }

    @Override
    public Result getShopList() {
        String str = redisUtil.get("shopList");
        if (MyStringUtil.isNullorEmpty(str)){
            List<Shop> list = userMapper.getShopList();
            Set<Integer> teamSet = new TreeSet<>();
            for (Shop shop: list) {
                teamSet.add(shop.getTeam());
            }
            JSONArray arry = new JSONArray();
            for (Integer teamIndex :teamSet) {
                JSONObject res = new JSONObject();
                List<Shop> shopList = new ArrayList<>();
                for (Shop shop: list){
                    if (teamIndex == shop.getTeam()){
                        shop.setArea(shop.getArea().replace("\r","").replace("\n",""));
                        shop.setAddress(shop.getAddress().replace("\r","").replace("\n",""));
                        shop.setPerson(shop.getPerson().replace("\r","").replace("\n",""));
                        String person = shop.getPerson();
                        person = person.charAt(0) + "经理";
                        shop.setPerson(person);
                        shop.setMobile(shop.getMobile().replace("\r","").replace("\n",""));
                        shop.setName(shop.getName().replace("\r","").replace("\n",""));
                        shopList.add(shop);
                    }
                }
                res.put("name", convertToTeamName(teamIndex));
                res.put("data", shopList);
                arry.add(res);
            }
            redisUtil.set("shopList", JSONArray.toJSONString(arry), 7000);
            return new Result().success("查询完成", arry);
        }else{
            JSONArray res = JSONArray.parseArray(str);
            return new Result().success("查询完成", res);
        }
    }

    @Override
    public Result getHelpRecord(String unionid) {
        UserHelp info = userMapper.getHelpInfo(unionid);
        List<UserHelp> list = userMapper.getHelpRecord(unionid);
        JSONObject res = new JSONObject();
        res.put("num", info.getNum());
        res.put("sum", info.getSum());
        res.put("list", list);
        return new Result().success("查询成功", res);
    }

    @Override
    public Result cityList() {
        String str = redisUtil.get("cityList");
        if (MyStringUtil.isNullorEmpty(str)){
            Integer baodingCode = 130600;
            List<AddressArea> firstList = userMapper.getAddressAreaByParentId(baodingCode);
            for (AddressArea area : firstList) {
                List<AddressArea> secondList = userMapper.getAddressAreaByParentId(area.getId());
                area.setChildList(secondList);
            }
            redisUtil.set("cityList", JSONArray.toJSONString(firstList), 7000);
            return  new Result().success("查询完成", firstList);
        }else{
            List<AddressArea> res = JSONArray.parseArray(str, AddressArea.class);
            return new Result().success("查询完成", res);
        }
    }

    private static String convertToTeamName(Integer teamIndex){
        if(teamIndex == 0){
            return "市区";
        }
        if(teamIndex == 1){
            return "一战区";
        }
        if(teamIndex == 2){
            return "二战区";
        }
        if(teamIndex == 3){
            return "三战区";
        }
        if(teamIndex == 4){
            return "四战区";
        }
        if(teamIndex == 5){
            return "五战区";
        }
        return "市区";
    }

    private void createPrizeInfo(UserOrder order,Integer win){
        Result result= prizeService.getPrizeById(win.longValue());
        List<Prize> list = JSONArray.parseArray(JSONObject.toJSONString(result.getData()), Prize.class);
        Prize prize=list.get(0);
        order.setPrizeName(prize.getPrizeName());
        order.setPrizeNum(prize.getPrizeNumber());
        order.setPrizeValue(prize.getPriceValue());
        order.setPId(win);
    }

//    private void createShopInfo(UserOrder order){
//        order.setContactName("李子木");
//        order.setContactMobile("15111111111");
//        order.setContactAddress("河北省保定市竞秀区关联云中心");
//    }

    private void createOrderNum(UserOrder order){
        String orderNum = randomStr(5);
        while(userMapper.checkOrderNum(orderNum) > 0){
            orderNum = randomStr(5);
        }
        order.setOrderNum(orderNum);
    }

    /**
     * 随机生成酒量（8至12范围）
     * @return
     */
    private static int randomAlcoholNum(){
        int [] alcoholNumArr = {8,9,10,11,12};
        Random random = new Random();
        int index = random.nextInt(5);
        int currentNum = alcoholNumArr[index];
        return currentNum;
    }

    /**
     * 41到50回生成酒量
     * @param currentAlcoholNum 当前酒量
     * @param helpedTimes 当前被帮助的次数
     * @return
     */
    private static int caclAlcoholNum(int currentAlcoholNum, int helpedTimes){
        //公式 (500-已累计酒量)/(50-已被帮助的的次数) 四舍五入
        int lackedNum = 500 - currentAlcoholNum;
        int lackTimes = 50 - helpedTimes;
        if (lackedNum <= 0 || lackTimes <= 0){
            return 0;
        }
        int currentNum = (int)Math.round((double)lackedNum / (double)lackTimes);
        return currentNum;
    }

    /**
     * 虚拟长度为100的数组，填充数据，乱序
     * @return
     */
    private static List<Integer> probabilityArray() {
        List<Integer> res = new ArrayList<Integer>();
        for (int i = 1; i <= 100; i++) {
            res.add(i);
        }
        Collections.shuffle(res);
        return res;
    }

    /**
     * 生成指定位数的随机数
     * @param length
     * @return
     */
    private static String randomStr(int length){
        StringBuffer res = new StringBuffer();
        Random r = new Random();
        while(res.length() < length){
            int number = r.nextInt(10);
            res.append(number);
        }
        return res.toString();
    }
    /**
          * 判断时间是否在时间段内
          * @param nowTime
          * @param beginTime
          * @param endTime
          * @return
          */
        public static boolean belongCalendar(Date nowTime, Date beginTime, Date endTime) {
            //设置当前时间
             Calendar date = Calendar.getInstance();
            date.setTime(nowTime);
            //设置开始时间
             Calendar begin = Calendar.getInstance();
             begin.setTime(beginTime);
            //设置结束时间
            Calendar end = Calendar.getInstance();
            end.setTime(endTime);
            //处于开始时间之后，和结束时间之前的判断
            if (date.after(begin) && date.before(end)) {
            return true;
            } else {
             return false;
            }
         }


}
